<div class="tmd-doc">
<h1 class="tmd-header-1">
Channels in Go
</h1>
<p></p>
<div class="tmd-usual">
Channel is an important built-in feature in Go. It is one of the features that makes Go unique. Along with another unique feature, <a href="control-flows-more.html#goroutine">goroutine</a>, channel makes concurrent programming convenient, fun and lowers the difficulties of concurrent programming.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
Channel mainly acts as a <a href="control-flows-more.html#synchronization">concurrency synchronization</a> technique. This article will list all the channel related concepts, syntax and rules. To understand channels better, the internal structure of channels and some implementation details by the standard Go compiler/runtime are also simply described.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
The information in this article may be slightly challenging for new gophers. Some parts of this article may need to be read several times to be fully understood.
</div>
<p></p>
<h3 class="tmd-header-3">
Channel Introduction
</h3>
<p></p>
<div class="tmd-usual">
One suggestion (made by <span class="tmd-italic">Rob Pike</span>) for concurrent programming is <span class="tmd-bold">don't (let computations) communicate by sharing memory, (let them) share memory by communicating (through channels)</span>. (We can view each computation as a goroutine in Go programming.)
</div>
<p></p>
<div class="tmd-usual">
Communicating by sharing memory and sharing memory by communicating are two programming manners in concurrent programming. When goroutines communicate by sharing memory, we use traditional concurrency synchronization techniques, such as mutex locks, to protect the shared memory to prevent data races. We can use channels to implement sharing memory by communicating.
</div>
<p></p>
<div class="tmd-usual">
Go provides a unique concurrency synchronization technique, channel. Channels make goroutines share memory by communicating. We can view a channel as an internal FIFO (first in, first out) queue within a program. Some goroutines send values to the queue (the channel) and some other goroutines receive values from the queue.
</div>
<p></p>
<div class="tmd-usual">
Along with transferring values (through channels), the ownership of some values may also be transferred between goroutines. When a goroutine sends a value to a channel, we can view the goroutine releases the ownership of some values (which could be accessed through the sent value). When a goroutine receives a value from a channel, we can view the goroutine acquires the ownership of some values (which could be accessed through the received value).
</div>
<p></p>
<div class="tmd-usual">
Surely, there may also not be any ownership transferred along with channel communications.
</div>
<p></p>
<div class="tmd-usual">
The values (whose ownerships are transferred) are often referenced (but are not required to be referenced) by the transferred value. Please note, here, when we talk about ownership, we mean the ownership from the logic view. Go channels can help programmers write data races free code easily, but Go channels can't prevent programmers from writing bad concurrent code from the syntax level.
</div>
<p></p>
<div class="tmd-usual">
Although Go also supports traditional concurrency synchronization techniques, only channel is first-class citizen in Go. Channel is one kind of types in Go, so we can use channels without importing any packages. On the other hand, those traditional concurrency synchronization techniques are provided in the <code class="tmd-code-span">sync</code> and <code class="tmd-code-span">sync/atomic</code> standard packages.
</div>
<p></p>
<div class="tmd-usual">
Honestly, each concurrency synchronization technique has its own best use scenarios. But channel has <a href="channel-use-cases.html">a wider application range and has more variety in using</a>. One problem of channels is, the experience of programming with channels is so enjoyable and fun that programmers often even prefer to use channels for the scenarios which channels are not best for.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Channel Types and Values
</h3>
<p></p>
<div class="tmd-usual">
Like array, slice and map, each channel type has an element type. A channel can only transfer values of the element type of the channel.
</div>
<p></p>
<div class="tmd-usual">
Channel types can be bi-directional or single-directional. Assume <code class="tmd-code-span">T</code> is an arbitrary type,
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">chan T</code> denotes a bidirectional channel type. Compilers allow both receiving values from and sending values to bidirectional channels.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">chan&lt;- T</code> denotes a send-only channel type. Compilers don't allow receiving values from send-only channels.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">&lt;-chan T</code> denotes a receive-only channel type. Compilers don't allow sending values to receive-only channels.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
<code class="tmd-code-span">T</code> is called the element type of these channel types.
</div>
<p></p>
<div class="tmd-usual">
Values of bidirectional channel type <code class="tmd-code-span">chan T</code> can be implicitly converted to both send-only type <code class="tmd-code-span">chan&lt;- T</code> and receive-only type <code class="tmd-code-span">&lt;-chan T</code>, but not vice versa (even if explicitly). Values of send-only type <code class="tmd-code-span">chan&lt;- T</code> can't be converted to receive-only type <code class="tmd-code-span">&lt;-chan T</code>, and vice versa. Note that the <code class="tmd-code-span">&lt;-</code> signs in channel type literals are modifiers.
</div>
<p></p>
<div class="tmd-usual">
Each channel value has a capacity, which will be explained in the section after next. A channel value with a zero capacity is called unbuffered channel and a channel value with a non-zero capacity is called buffered channel.
</div>
<p></p>
<div class="tmd-usual">
The zero values of channel types are represented with the predeclared identifier <code class="tmd-code-span">nil</code>. A non-nil channel value must be created by using the built-in <code class="tmd-code-span">make</code> function. For example, <code class="tmd-code-span">make(chan int, 10)</code> will create a channel whose element type is <code class="tmd-code-span">int</code>. The second argument of the <code class="tmd-code-span">make</code> function call specifies the capacity of the new created channel. The second parameter is optional and its default value is zero.
</div>
<p></p>
<h3 id="assign-and-compare" class="tmd-header-3">
Channel Value Comparisons
</h3>
<p></p>
<div class="tmd-usual">
All channel types are comparable types.
</div>
<p></p>
<div class="tmd-usual">
From the article <a href="value-part.html">value parts</a>, we know that non-nil channel values are multi-part values. If one channel value is assigned to another, the two channels share the same underlying part(s). In other words, those two channels represent the same internal channel object. The result of comparing them is <code class="tmd-code-span">true</code>.
</div>
<p></p>
<p></p>
<h3 id="operations" class="tmd-header-3">
Channel Operations
</h3>
<p></p>
<div class="tmd-usual">
There are five channel specified operations. Assume the channel is <code class="tmd-code-span">ch</code>, their syntax and function calls of these operations are listed here.
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
Close the channel by using the following function call
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">close(ch)
</code></pre>
<div class="tmd-usual">
where <code class="tmd-code-span">close</code> is a built-in function. The argument of a <code class="tmd-code-span">close</code> function call must be a channel value, and the channel <code class="tmd-code-span">ch</code> must not be a receive-only channel.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Send a value, <code class="tmd-code-span">v</code>, to the channel by using the following syntax
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">ch &lt;- v
</code></pre>
<div class="tmd-usual">
where <code class="tmd-code-span">v</code> must be a value which is assignable to the element type of channel <code class="tmd-code-span">ch</code>, and the channel <code class="tmd-code-span">ch</code> must not be a receive-only channel. Note that here <code class="tmd-code-span">&lt;-</code> is a channel-send operator.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Receive a value from the channel by using the following syntax
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">&lt;-ch
</code></pre>
<div class="tmd-usual">
A channel receive operation always returns at least one result, which is a value of the element type of the channel, and the channel <code class="tmd-code-span">ch</code> must not be a send-only channel. Note that here <code class="tmd-code-span">&lt;-</code> is a channel-receive operator. Yes, its representation is the same as a channel-send operator.
</div>
<p />
<div class="tmd-usual">
For most scenarios, a channel receive operation is viewed as a single-value expression. However, when a channel operation is used as the only source value expression in an assignment, it can result a second optional untyped boolean value and become a multi-value expression. The untyped boolean value indicates whether or not the first result is sent before the channel is closed. (Below we will learn that we can receive unlimited number of values from a closed channel.)
</div>
<p />
<div class="tmd-usual">
Two channel receive operations which are used as source values in assignments:
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">v = &lt;-ch
v, sentBeforeClosed = &lt;-ch
</code></pre>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Query the value buffer capacity of the channel by using the following function call
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">cap(ch)
</code></pre>
<div class="tmd-usual">
where <code class="tmd-code-span">cap</code> is a built-in function which has been introduced in <a href="container.html#cap-len">containers in Go</a>. The return result of a <code class="tmd-code-span">cap</code> function call is an <code class="tmd-code-span">int</code> value.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Query the current number of values in the value buffer (or the length) of the channel by using the following function call
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">len(ch)
</code></pre>
<div class="tmd-usual">
where <code class="tmd-code-span">len</code> is a built-in function which also has been introduced before. The return value of a <code class="tmd-code-span">len</code> function call is an <code class="tmd-code-span">int</code> value. The result length is the number of elements which have already been sent successfully to the queried channel but haven't been received (taken out) yet.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
Most basic operations in Go are not synchronized. In other words, they are not concurrency-safe. These operations include value assignments, argument passing and container element manipulations, etc. However, all the just introduced channel operations are already synchronized, so no further synchronizations are needed to safely perform these operations.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
Like most other operations in Go, channel value assignments are not synchronized. Similarly, assigning the received value to another value is also not synchronized, though any channel receive operation is synchronized.
</div>
<p></p>
<div class="tmd-usual">
If the queried channel is a nil channel, both of the built-in <code class="tmd-code-span">cap</code> and <code class="tmd-code-span">len</code> functions return zero. The two query operations are so simple that they will not get further explanations later. In fact, the two operations are seldom used in practice.
</div>
<p></p>
<div class="tmd-usual">
Channel send, receive and close operations will be explained in detail in the next section.
</div>
<p></p>
<h3 id="channel-operation-explanations" class="tmd-header-3">
Detailed Explanations for Channel Operations
</h3>
<p></p>
<div class="tmd-usual">
To make the explanations for channel operations simple and clear, in the remaining of this article, channels will be classified into three categories:
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
nil channels.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
non-nil but closed channels.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
not-closed non-nil channels.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
The following table simply summarizes the behaviors for all kinds of operations applying on nil, closed and not-closed non-nil channels.
</div>
<p></p>
<table class="tmd-table table table-bordered text-center">
<tr>
<th>
Operation
</th>
<th>
A Nil Channel
</th>
<th>
A Closed Channel
</th>
<th>
A Not-Closed Non-Nil Channel
</th>
</tr>
<tr>
<th>
Close
</th>
<td>
<div class="tmd-usual">
panic
</div>
</td>
<td>
<div class="tmd-usual">
panic
</div>
</td>
<td>
<div class="tmd-usual">
succeed to close <sup>(C)</sup>
</div>
</td>
</tr>
<tr>
<th>
Send Value To
</th>
<td>
<div class="tmd-usual">
block for ever
</div>
</td>
<td>
<div class="tmd-usual">
panic
</div>
</td>
<td>
<div class="tmd-usual">
block or succeed to send <sup>(B)</sup>
</div>
</td>
</tr>
<tr>
<th>
Receive Value From
</th>
<td>
<div class="tmd-usual">
block for ever
</div>
</td>
<td>
<div class="tmd-usual">
never block <sup>(D)</sup>
</div>
</td>
<td>
<div class="tmd-usual">
block or succeed to receive <sup>(A)</sup>
</div>
</td>
</tr>
</table>
<p></p>
<div class="tmd-usual">
For the five cases shown without superscripts, the behaviors are very clear.
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
Closing a nil or an already closed channel produces a panic in the current goroutine.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Sending a value to a closed channel also produces a panic in the current goroutine.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Sending a value to or receiving a value from a nil channel makes the current goroutine enter and stay in blocking state for ever.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
The following will make more explanations for the four cases shown with superscripts (A, B, C and D).
</div>
<p></p>
<div class="tmd-usual">
To better understand channel types and values, and to make some explanations easier, looking in the raw internal structures of internal channel objects is very helpful.
</div>
<p></p>
<div class="tmd-usual">
We can think of each channel consisting of three queues (all can be viewed as FIFO queues) internally:
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
the receiving goroutine queue (generally FIFO). The queue is a linked list without size limitation. Goroutines in this queue are all in blocking state and waiting to receive values from that channel.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the sending goroutine queue (generally FIFO). The queue is also a linked list without size limitation. Goroutines in this queue are all in blocking state and waiting to send values to that channel. The value (or the address of the value, depending on compiler implementation) each goroutine is trying to send is also stored in the queue along with that goroutine.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the value buffer queue (absolutely FIFO). This is a circular queue. Its size is equal to the capacity of the channel. The types of the values stored in this buffer queue are all the element type of that channel. If the current number of values stored in the value buffer queue of the channel reaches the capacity of the channel, the channel is called in full status. If no values are stored in the value buffer queue of the channel currently, the channel is called in empty status. For a zero-capacity (unbuffered) channel, it is always in both full and empty status.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
Each channel internally holds a mutex lock which is used to avoid data races in all kinds of operations.
</div>
<p></p>
<div class="tmd-usual">
<span class="tmd-underlined"><span class="tmd-bold">Channel operation case A</span>: when a goroutine <code class="tmd-code-span">R</code> tries to receive a value from a not-closed non-nil channel</span>, the goroutine <code class="tmd-code-span">R</code> will acquire the lock associated with the channel firstly, then do the following steps until one condition is satisfied.
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
If the value buffer queue of the channel is not empty, in which case the receiving goroutine queue of the channel must be empty, the goroutine <code class="tmd-code-span">R</code> will receive (by shifting) a value from the value buffer queue. If the sending goroutine queue of the channel is also not empty, a sending goroutine will be shifted out of the sending goroutine queue and resumed to running state again. The value that the just shifted sending goroutine is trying to send will be pushed into the value buffer queue of the channel. The receiving goroutine <code class="tmd-code-span">R</code> continues running. For this scenario, the channel receive operation is called a <span class="tmd-bold">non-blocking operation</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Otherwise (the value buffer queue of the channel is empty), if the sending goroutine queue of the channel is not empty, in which case the channel must be an unbuffered channel, the receiving goroutine <code class="tmd-code-span">R</code> will shift a sending goroutine from the sending goroutine queue of the channel and receive the value that the just shifted sending goroutine is trying to send. The just shifted sending goroutine will get unblocked and resumed to running state again. The receiving goroutine <code class="tmd-code-span">R</code> continues running. For this scenario, the channel receive operation is called a <span class="tmd-bold">non-blocking operation</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If value buffer queue and the sending goroutine queue of the channel are both empty, the goroutine <code class="tmd-code-span">R</code> will be pushed into the receiving goroutine queue of the channel and enter (and stay in) blocking state. It may be resumed to running state when another goroutine sends a value to the channel later. For this scenario, the channel receive operation is called a <span class="tmd-bold">blocking operation</span>.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
<span class="tmd-underlined"><span class="tmd-bold">Channel rule case B</span>: when a goroutine <code class="tmd-code-span">S</code> tries to send a value to a not-closed non-nil channel</span>, the goroutine <code class="tmd-code-span">S</code> will acquire the lock associated with the channel firstly, then do the following steps until one step condition is satisfied.
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
If the receiving goroutine queue of the channel is not empty, in which case the value buffer queue of the channel must be empty, the sending goroutine <code class="tmd-code-span">S</code> will shift a receiving goroutine from the receiving goroutine queue of the channel and send the value to the just shifted receiving goroutine. The just shifted receiving goroutine will get unblocked and resumed to running state again. The sending goroutine <code class="tmd-code-span">S</code> continues running. For this scenario, the channel send operation is called a <span class="tmd-bold">non-blocking operation</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Otherwise (the receiving goroutine queue is empty), if the value buffer queue of the channel is not full, in which case the sending goroutine queue must be also empty, the value the sending goroutine <code class="tmd-code-span">S</code> trying to send will be pushed into the value buffer queue, and the sending goroutine <code class="tmd-code-span">S</code> continues running. For this scenario, the channel send operation is called a <span class="tmd-bold">non-blocking operation</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If the receiving goroutine queue is empty and the value buffer queue of the channel is already full, the sending goroutine <code class="tmd-code-span">S</code> will be pushed into the sending goroutine queue of the channel and enter (and stay in) blocking state. It may be resumed to running state when another goroutine receives a value from the channel later. For this scenario, the channel send operation is called a <span class="tmd-bold">blocking operation</span>.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
Above has mentioned, once a non-nil channel is closed, sending a value to the channel will produce a runtime panic in the current goroutine. Note, sending data to a closed channel is viewed as a <span class="tmd-bold">non-blocking operation</span>.
</div>
<p></p>
<div class="tmd-usual">
<span class="tmd-underlined"><span class="tmd-bold">Channel operation case C</span>: when a goroutine tries to close a not-closed non-nil channel</span>, once the goroutine has acquired the lock of the channel, both of the following two steps will be performed by the following order.
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
If the receiving goroutine queue of the channel is not empty, in which case the value buffer of the channel must be empty, all the goroutines in the receiving goroutine queue of the channel will be shifted one by one, each of them will receive a zero value of the element type of the channel and be resumed to running state.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If the sending goroutine queue of the channel is not empty, all the goroutines in the sending goroutine queue of the channel will be shifted one by one and each of them will produce a panic for sending on a closed channel. This is the reason why we should avoid concurrent send and close operations on the same channel. In fact, when <a href="https://golang.org/doc/articles/race_detector.html">the go command's data race detector option</a> (<code class="tmd-code-span">-race</code>) is enabled, concurrent send and close operation cases might be detected at run time and a runtime panic will be thrown.
</div>
</li>
</ol>
<p></p>
<p></p>
<div class="tmd-usual">
Note: after a channel is closed, the values which have been already pushed into the value buffer of the channel are still there. Please read the closely following explanations for case D for details.
</div>
<p></p>
<div class="tmd-usual">
<span class="tmd-underlined"><span class="tmd-bold">Channel operation case D</span>: after a non-nil channel is closed, channel receive operations on the channel will never block</span>. The values in the value buffer of the channel can still be received. The accompanying second optional bool return values are still <code class="tmd-code-span">true</code>. Once all the values in the value buffer are taken out and received, infinite zero values of the element type of the channel will be received by any of the following receive operations on the channel. As mentioned above, the optional second return result of a channel receive operation is an untyped boolean value which indicates whether or not the first result (the received value) is sent before the channel is closed. If the second return result is <code class="tmd-code-span">false</code>, then the first return result (the received value) must be a zero value of the element type of the channel.
</div>
<p></p>
<div class="tmd-usual">
Knowing what are blocking and non-blocking channel send or receive operations is important to understand the mechanism of <code class="tmd-code-span">select</code> control flow blocks which will be introduced in a later section.
</div>
<p></p>
<div class="tmd-usual">
In the above explanations, if a goroutine is shifted out of a queue (either the sending or the receiving goroutine queue) of a channel, and the goroutine was blocked for being pushed into the queue at a <a href="#select"><code class="tmd-code-span">select</code> control flow code block</a>, then the goroutine will be resumed to running state at step <span class="tmd-italic">9</span> of the <a href="#select-implementation"><code class="tmd-code-span">select</code> control flow code block execution</a>. It may be dequeued from the corresponding goroutine queue of several channels involved in the <code class="tmd-code-span">select</code> control flow code block.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
According to the explanations listed above, we can get some facts about the internal queues of a channel.
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
If the channel is closed, both its sending goroutine queue and receiving goroutine queue must be empty, but its value buffer queue may not be empty.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
At any time, if the value buffer is not empty, then its receiving goroutine queue must be empty.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
At any time, if the value buffer is not full, then its sending goroutine queue must be empty.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If the channel is buffered, then at any time, at least one of the channel's goroutine queues must be empty (sending, receiving, or both).
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If the channel is unbuffered, most of the time one of its sending goroutine queue and the receiving goroutine queue must be empty, with one exception. The exception is that a goroutine may be pushed into both of the two queues when executing a <a href="#select"><code class="tmd-code-span">select</code> control flow code block</a>.
</div>
</li>
</ol>
<p></p>
<h3 class="tmd-header-3">
Some Channel Use Examples
</h3>
<p></p>
<div class="tmd-usual">
Now that you've read the above section, let's view some examples which use channels to enhance your understanding.
</div>
<p></p>
<div class="tmd-usual">
A simple request/response example. The two goroutines in this example talk to each other through an unbuffered channel.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan int) // an unbuffered channel
	go func(ch chan&lt;- int, x int) {
		time.Sleep(time.Second)
		// &lt;-ch    // fails to compile
		// Send the value and block until the result is received.
		ch &lt;- x*x // 9 is sent
	}(c, 3)
	done := make(chan struct{})
	go func(ch &lt;-chan int) {
		// Block until 9 is received.
		n := &lt;-ch
		fmt.Println(n) // 9
		// ch &lt;- 123   // fails to compile
		time.Sleep(time.Second)
		done &lt;- struct{}{}
	}(c)
	// Block here until a value is received by
	// the channel "done".
	&lt;-done
	fmt.Println("bye")
}
</code></pre>
<p></p>
<div class="tmd-usual">
The output:
</div>
<pre class="tmd-code output">
9
bye
</pre>
<p></p>
<div class="tmd-usual">
A demo of using a buffered channel. This program is not a concurrent one, it just shows how to use buffered channels.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import "fmt"

func main() {
	c := make(chan int, 2) // a buffered channel
	c &lt;- 3
	c &lt;- 5
	close(c)
	fmt.Println(len(c), cap(c)) // 2 2
	x, ok := &lt;-c
	fmt.Println(x, ok) // 3 true
	fmt.Println(len(c), cap(c)) // 1 2
	x, ok = &lt;-c
	fmt.Println(x, ok) // 5 true
	fmt.Println(len(c), cap(c)) // 0 2
	x, ok = &lt;-c
	fmt.Println(x, ok) // 0 false
	x, ok = &lt;-c
	fmt.Println(x, ok) // 0 false
	fmt.Println(len(c), cap(c)) // 0 2
	close(c) // panic!
	// The send will also panic if the above
	// close call is removed.
	c &lt;- 7
}
</code></pre>
<p></p>
<div class="tmd-usual">
A never-ending football game.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"time"
)

func main() {
	var ball = make(chan string)
	kickBall := func(playerName string) {
		for {
			fmt.Println(&lt;-ball, "kicked the ball.")
			time.Sleep(time.Second)
			ball &lt;- playerName
		}
	}
	go kickBall("John")
	go kickBall("Alice")
	go kickBall("Bob")
	go kickBall("Emily")
	ball &lt;- "referee" // kick off
	var c chan bool   // nil
	&lt;-c               // blocking here for ever
}
</code></pre>
<p></p>
<div class="tmd-usual">
Please read <a href="channel-use-cases.html">channel use cases</a> for more channel use examples.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Channel Element Values Are Transferred by Copy
</h3>
<p></p>
<div class="tmd-usual">
When a value is transferred from one goroutine to another goroutine, the value will be copied at least one time. If the transferred value ever stayed in the value buffer of a channel, then two copies will happen in the transfer process. One copy happens when the value is copied from the sender goroutine into the value buffer, the other happens when the value is copied from the value buffer to the receiver goroutine. Like value assignments and function argument passing, when a value is transferred, <a href="value-part.html#about-value-copy">only its direct part is copied</a>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
For the standard Go compiler, the size of channel element types must be smaller than <code class="tmd-code-span">65536</code>. However, generally, we shouldn't create channels with large-size element types, to avoid too large copy cost in the process of transferring values between goroutines. So if the passed value size is too large, it is best to use a pointer element type instead, to avoid a large value copy cost.
</div>
<p></p>
<h3 class="tmd-header-3">
About Channel and Goroutine Garbage Collections
</h3>
<p></p>
<div class="tmd-usual">
Note, a channel is referenced by all the goroutines in either the sending or the receiving goroutine queue of the channel, so if neither of the queues of the channel is empty, the channel cannot be garbage collected. On the other hand, if a goroutine is blocked and stays in either the sending or the receiving goroutine queue of a channel, then the goroutine also cannot be garbage collected, even if the channel is referenced only by this goroutine. In fact, a goroutine can only be garbage collected when it has already exited.
</div>
<p></p>
<h3 class="tmd-header-3">
Channel Send and Receive Operations Are Simple Statements
</h3>
<p></p>
<div class="tmd-usual">
Channel send operations and receive operations are <a href="expressions-and-statements.html#simple-statements">simple statements</a>. A channel receive operation can be always used as a single-value expression. Simple statements and expressions can be used at certain portions of <a href="control-flows.html">basic control flow blocks</a>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
An example in which channel send and receive operations appear as simple statements in two <code class="tmd-code-span">for</code> control flow blocks.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"time"
)

func main() {
	fibonacci := func() chan uint64 {
		c := make(chan uint64)
		go func() {
			var x, y uint64 = 0, 1
			for ; y &lt; (1 &lt;&lt; 63); c &lt;- y { // here
				x, y = y, x+y
			}
			close(c)
		}()
		return c
	}
	c := fibonacci()
	for x, ok := &lt;-c; ok; x, ok = &lt;-c { // here
		time.Sleep(time.Second)
		fmt.Println(x)
	}
}
</code></pre>
<p></p>
<h3 id="range" class="tmd-header-3">
<code class="tmd-code-span">for-range</code> on Channels
</h3>
<p></p>
<div class="tmd-usual">
The <code class="tmd-code-span">for-range</code> control flow code block applies to channels. The loop will try to iteratively receive the values sent to a channel, until the channel is closed and its value buffer queue becomes blank. With <code class="tmd-code-span">for-range</code> syntax on arrays, slices and maps, multiple iteration variables are allowed. However, for <code class="tmd-code-span">for-range</code> blocks applied to channels, you can use at most one iteration variable, which is used to store the received values.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">for v := range aChannel {
	// use v
}
</code></pre>
<p></p>
<div class="tmd-usual">
is equivalent to
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">for {
	v, ok = &lt;-aChannel
	if !ok {
		break
	}
	// use v
}
</code></pre>
<p></p>
<div class="tmd-usual">
Surely, here the <code class="tmd-code-span">aChannel</code> value must not be a send-only channel. If it is a nil channel, the loop will block there for ever.
</div>
<p></p>
<div class="tmd-usual">
For example, the second <code class="tmd-code-span">for</code> loop block in the example shown in the last section can be simplified to
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">	for x := range c {
		time.Sleep(time.Second)
		fmt.Println(x)
	}
</code></pre>
<p></p>
<h3 id="select" class="tmd-header-3">
<code class="tmd-code-span">select-case</code> Control Flow Code Blocks
</h3>
<p></p>
<div class="tmd-usual">
There is a <code class="tmd-code-span">select-case</code> code block syntax which is specially designed for channels. The syntax is much like the <code class="tmd-code-span">switch-case</code> block syntax. For example, there can be multiple <code class="tmd-code-span">case</code> branches and at most one <code class="tmd-code-span">default</code> branch in the <code class="tmd-code-span">select-case</code> code block. But there are also some obvious differences between them.
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
No expressions and statements are allowed to follow the <code class="tmd-code-span">select</code> keyword (before <code class="tmd-code-span">{</code>).
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
No <code class="tmd-code-span">fallthrough</code> statements are allowed to be used in <code class="tmd-code-span">case</code> branches.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Each statement following a <code class="tmd-code-span">case</code> keyword in a <code class="tmd-code-span">select-case</code> code block must be either a channel receive operation or a channel send operation statement. A channel receive operation can appear as the source value of a simple assignment statement. Later, a channel operation following a <code class="tmd-code-span">case</code> keyword will be called a <code class="tmd-code-span">case</code> operation.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If there are one or more non-blocking <code class="tmd-code-span">case</code> operations, Go runtime will <span class="tmd-bold">randomly select one of these non-blocking operations to execute</span>, then continue to execute the corresponding <code class="tmd-code-span">case</code> branch.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
If all the <code class="tmd-code-span">case</code> operations in a <code class="tmd-code-span">select-case</code> code block are blocking operations, the <code class="tmd-code-span">default</code> branch will be selected to execute if the <code class="tmd-code-span">default</code> branch is present. If the <code class="tmd-code-span">default</code> branch is absent, the current goroutine will be pushed into the corresponding sending goroutine queue or receiving goroutine queue of every channel involved in all <code class="tmd-code-span">case</code> operations, then enter blocking state.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
By the rules, a <code class="tmd-code-span">select-case</code> code block without any branches, <code class="tmd-code-span">select{}</code>, will make the current goroutine stay in blocking state forever.
</div>
<p></p>
<div class="tmd-usual">
The following program will enter the <code class="tmd-code-span">default</code> branch for sure.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import "fmt"

func main() {
	var c chan struct{} // nil
	select {
	case &lt;-c:             // blocking operation
	case c &lt;- struct{}{}: // blocking operation
	default:
		fmt.Println("Go here.")
	}
}
</code></pre>
<p></p>
<div class="tmd-usual">
An example showing how to use try-send and try-receive:
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import "fmt"

func main() {
	c := make(chan string, 2)
	trySend := func(v string) {
		select {
		case c &lt;- v:
		default: // go here if c is full.
		}
	}
	tryReceive := func() string {
		select {
		case v := &lt;-c: return v
		default: return "-" // go here if c is empty
		}
	}
	trySend("Hello!") // succeed to send
	trySend("Hi!")    // succeed to send
	// Fail to send, but will not block.
	trySend("Bye!")
	// The following two lines will
	// both succeed to receive.
	fmt.Println(tryReceive()) // Hello!
	fmt.Println(tryReceive()) // Hi!
	// The following line fails to receive.
	fmt.Println(tryReceive()) // -
}
</code></pre>
<p></p>
<div class="tmd-usual">
The following example has 50% possibility to panic. Both of the two <code class="tmd-code-span">case</code> operations are non-blocking in this example.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

func main() {
	c := make(chan struct{})
	close(c)
	select {
	case c &lt;- struct{}{}:
		// Panic if the first case is selected.
	case &lt;-c:
	}
}
</code></pre>
<p></p>
<h3 id="select-implementation" class="tmd-header-3">
The Implementation of the Select Mechanism
</h3>
<p></p>
<div class="tmd-usual">
The select mechanism in Go is an important and unique feature. Here the steps of <a href="https://github.com/golang/go/blob/master/src/runtime/select.go">the select mechanism implementation by the official Go runtime</a> are listed.
</div>
<p></p>
<p></p>
<p></p>
<div class="tmd-usual">
There are several steps to execute a <code class="tmd-code-span">select-case</code> block:
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
evaluate all involved channel expressions and value expressions to be potentially sent in <code class="tmd-code-span">case</code> operations, from top to bottom and left to right. Destination values for receive operations (as source values) in assignments needn't be evaluated at this time.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
randomize the branch orders for polling in step <span class="tmd-italic">5</span>. The <code class="tmd-code-span">default</code> branch is always put at the last position in the result order. Channels may be duplicate in the <code class="tmd-code-span">case</code> operations.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
sort all involved channels in the <code class="tmd-code-span">case</code> operations to avoid deadlock (with other goroutines) in the next step. No duplicate channels stay in the first <code class="tmd-code-span">N</code> channels of the sorted result, where <code class="tmd-code-span">N</code> is the number of involved channels in the <code class="tmd-code-span">case</code> operations. Below, the <span class="tmd-bold"><span class="tmd-italic">channel lock order</span></span> is a concept for the first <code class="tmd-code-span">N</code> channels in the sorted result.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
lock (a.k.a., acquire the locks of) all involved channels by the channel lock order produced in last step.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
poll each branch in the select block by the randomized order produced in step <span class="tmd-italic">2</span>:
</div>
<div class="tmd-base">
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
if this is a <code class="tmd-code-span">case</code> branch and the corresponding channel operation is a send-value-to-closed-channel operation, unlock all channels by the inverse channel lock order and make the current goroutine panic. Go to step <span class="tmd-italic">12</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
if this is a <code class="tmd-code-span">case</code> branch and the corresponding channel operation is non-blocking, perform the channel operation and unlock all channels by the inverse channel lock order, then execute the corresponding <code class="tmd-code-span">case</code> branch body. The channel operation may wake up another goroutine in blocking state. Go to step <span class="tmd-italic">12</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
if this is the <code class="tmd-code-span">default</code> branch, then unlock all channels by the inverse channel lock order and execute the <code class="tmd-code-span">default</code> branch body. Go to step <span class="tmd-italic">12</span>.
</div>
</li>
</ol>
<p></p>
</div>
<div class="tmd-usual">
(Up to here, the <code class="tmd-code-span">default</code> branch is absent and all <code class="tmd-code-span">case</code> operations are blocking operations.)
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
push (enqueue) the current goroutine (along with the information of the corresponding <code class="tmd-code-span">case</code> branch) into the receiving or sending goroutine queue of the involved channel in each <code class="tmd-code-span">case</code> operation. The current goroutine may be pushed into the queues of a channel for multiple times, for the involved channels in multiple cases may be the same one.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
make the current goroutine enter blocking state and unlock all channels by the inverse channel lock order.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
wait in blocking state until other channel operations wake up the current goroutine, ...
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the current goroutine is waken up by another channel operation in another goroutine. The other operation may be a channel close operation or a channel send/receive operation. If it is a channel send/receive operation, there must be a <code class="tmd-code-span">case</code> channel receive/send operation (in the current being explained <code class="tmd-code-span">select-case</code> block) cooperating with it (by transferring a value). In the cooperation, the current goroutine will be dequeued from the receiving/sending goroutine queue of the channel.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
lock all involved channels by the channel lock order.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
dequeue the current goroutine from the receiving goroutine queue or sending goroutine queue of the involved channel in each <code class="tmd-code-span">case</code> operation,
</div>
<div class="tmd-base">
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
if the current goroutine is waken up by a channel close operation, go to step <span class="tmd-italic">5</span>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
if the current goroutine is waken up by a channel send/receive operation, the corresponding <code class="tmd-code-span">case</code> branch of the cooperating receive/send operation has already been found in the dequeuing process, so just unlock all channels by the inverse channel lock order and execute the corresponding <code class="tmd-code-span">case</code> branch.
</div>
</li>
</ol>
</div>
<p></p>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
done.
</div>
</li>
</ol>
<p></p>
<div class="tmd-usual">
From the implementation, we know that
</div>
<ol class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
a goroutine may stay in the sending goroutine queues and the receiving goroutine queues of multiple channels at the same time. It can even stay in the sending goroutine queue and the receiving goroutine queue of the same channel at the same time.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
when a goroutine currently being blocked at a <code class="tmd-code-span">select-case</code> code block gets resumed later, it will be removed from all the sending goroutine queues and the receiving goroutine queues of all channels involved in the channel operations following <code class="tmd-code-span">case</code> keywords in the <code class="tmd-code-span">select-case</code> code block.
</div>
</li>
</ol>
<p></p>
<h3 class="tmd-header-3">
More
</h3>
<p></p>
<div class="tmd-usual">
We can find more channel use cases in <a href="channel-use-cases.html">this article</a>.
</div>
<p></p>
<div class="tmd-usual">
Although channels can help us write <a href="channel-closing.html">correct concurrent code easily</a>, like other data synchronization techniques, channels will not prevent us from <a href="concurrent-common-mistakes.html">writing improper concurrent code</a>.
</div>
<p></p>
<div class="tmd-usual">
Channel may be not always the best solution for all use cases for data synchronizations. Please read <a href="concurrent-synchronization-more.html">this article</a> and <a href="concurrent-atomic-operation.html">this article</a> for more synchronization techniques in Go.
</div>
<p></p>
<p></p>
</div>
